package com.klikmee.sms.core.base.subscription;

import java.util.Date;
import java.util.Hashtable;
import java.util.List;

import org.apache.log4j.Logger;

import com.klikmee.sms.core.base.dao.DistributionListDAO;
import com.klikmee.sms.core.base.dao.DistributionListItemDAO;
import com.klikmee.sms.core.base.postman.ServiceMessageDeliverer;
import com.klikmee.sms.core.model.DistributionList;
import com.klikmee.sms.core.model.DistributionListItem;

public class MtsSubscriptionManager implements SubscriptionManager {

	private DistributionListDAO		distributionListDAO		= null;
	private DistributionListItemDAO	distributionListItemDAO;
	private Logger					logger					= Logger.getLogger( MtsSubscriptionManager.class );
	private ServiceMessageDeliverer	serviceMessageDeliverer	= null;

	public Hashtable<String, String> getSubscriptionDetail( String serviceId, String message ) throws NoDistributionListFoundException {
		// find all distribution list for this service
		List<DistributionList> distributionLists = distributionListDAO.findByMTSServiceId( serviceId );
		// if no lists are found throw NoListFoundException
		if (distributionLists == null || distributionLists.isEmpty()) {
			throw new NoDistributionListFoundException( String.format( "No distribution list found for MTSServiceId = [%s]", serviceId ) );
		}

		// iterate trough list and test subscribe regex against user message text
		DistributionList matchingList = null;
		for (DistributionList currentList : distributionLists) {

			if (message.matches( currentList.getSubscribeRegEx() )) {
				matchingList = currentList;
				break;
			}
		}

		// if no list was found throw exception
		if (matchingList == null) {
			throw new NoDistributionListFoundException( String.format( "Non of [%s] distribution lists match subscription pattern", distributionLists.size() ) );
		}

		// return data of the matching distribution list
		Hashtable<String, String> result = new Hashtable<String, String>();
		result.put( SubscriptionManager.DISTRIBUTION_LIST_ID, matchingList.getListMTSId() );
		result.put( SubscriptionManager.DISTRIBUTION_LIST_NAME, matchingList.getListName() );

		return result;
	}

	public void receiveSubacription( String msisdn, String serviceId, String distributionListId, Date validTo ) {

		try {
			// find distribution list by id and service id
			DistributionList distributionList = distributionListDAO.findByMtsServiceIdAndMtsListId( serviceId, distributionListId );

			// create distribution list item
			DistributionListItem item = new DistributionListItem();
			item.setDistributionList( distributionList );
			item.setPhoneNumber( msisdn );
			item.setValidTo( validTo );

			this.distributionListItemDAO.create( item );
			
			// notify service instance
			this.serviceMessageDeliverer.forwardSubscripitonRequest( distributionList.getService(), distributionListId, msisdn, validTo );

		} catch (Exception e) {
			// in case of any exception log it
			logger.fatal( "Unexpected error while creating distributionList item", e );
		}

	}

	public void receiveUnsubscription( String msisdn, String serviceId, String distributionListId ) {
		// find distributionlist item
		try {

			// if distribuitonListId is null then delete msisdn from all distribution lists
			if (distributionListId == null) {
				this.distributionListItemDAO.deleteByMsisdn( msisdn );
			} 
			
			// else delete it just from specific one
			else {
				DistributionListItem item = this.distributionListItemDAO.findByMtsServiceIdListIdAndMsisdn( serviceId, distributionListId, msisdn );
				if (item != null) {
					// delete from db
					distributionListItemDAO.remove( item );
				}
			}

		} catch (Exception e) {
			logger.fatal( String.format( "Unexpeced error when deleting list item, msisdn = [%s], mtsServiceId = [%s], mtsListId = [%s]", msisdn, serviceId, distributionListId ), e );
		}

	}

	public void receiveSubscriptionExtension( String msisdn, String serviceId, String distributionListId, Date validTo ) {
		// find distributionlist item
		try {
			DistributionListItem item = this.distributionListItemDAO.findByMtsServiceIdListIdAndMsisdn( serviceId, distributionListId, msisdn );
			if (item != null) {
				// update valid to value
				item.setValidTo( validTo );

				// merge
				distributionListItemDAO.edit( item );
			}
		} catch (Exception e) {
			logger.fatal( String.format( "Unexpeced error when extending subscription, msisdn = [%s], mtsServiceId = [%s], mtsListId = [%s]", msisdn, serviceId, distributionListId ), e );
		}
	}

	public void setDistributionListDAO( DistributionListDAO distributionListDAO ) {
		this.distributionListDAO = distributionListDAO;
	}

	public void setDistributionListItemDAO( DistributionListItemDAO distributionListItemDAO ) {
		this.distributionListItemDAO = distributionListItemDAO;
	}

}
